/**
 * 
 */
package cz.cuni.mff.abacs.burglar.visual;

import cz.cuni.mff.abacs.burglar.visual.play_state.GraphicPlayState;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;


/**
 * Main class of the game part of the program.
 * 
 * @author abacs
 *
 */
public class VisualBurglar extends StateBasedGame {
	
	// constants:
	
	/** The string put into the title bar. */
	protected static final String STR_TITLE = "Visual Burglar";
	
	
	protected static final String STR_RESOURCES = "-resources";
	protected static final String STR_HEIGHT = "-height";
	protected static final String STR_WIDTH = "-width";
	protected static final String STR_FULLSCREEN = "-full";
	protected static final String STR_FRAMERATE = "-rate";
	protected static final String STR_REPLAN_ON_KNOWLEDGE = "-replan_on_knowledge";
	
	/** The string printed to the user if the input parameters are invalid. */
	protected static final String STR_USAGE = 
		"game usage:\n" + 
		"\t[" + STR_WIDTH + " %d]\twidth\n" +
		"\t[" + STR_HEIGHT + " %d]\theight\n" +
		"\t[" + STR_FRAMERATE + "]\tshow frame rate\n" +
		"\t[" + STR_FULLSCREEN + "]\tfull screen mode\n" +
		"\t[" + STR_RESOURCES + " %s]\tlocation of the resources directory (default is \"./resources/\")" +
		"\t[" + STR_REPLAN_ON_KNOWLEDGE + "]\treplan when new knowledge is available\n";
		
	
	// -------------------------------------------------------------------------
	
	
	/** The default width of the drawing area. */
	protected static int DEFAULT_WIDTH  = 1200;
	/** The default height of the drawing area. */
	protected static int DEFAULT_HEIGHT = 800;
	
	
	// -------------------------------------------------------------------------
	// state identifiers:
	
	public static final int STATE_MENU = 1;
    public static final int STATE_PLAY = 2;
	public static final int STATE_LEVEL_SELECT = 3;
	
	
	// -------------------------------------------------------------------------
	
	
    /** The default width and height of the images in the resource directory. */
	public static final int RESOURCE_BLOCK_SIZE = 32;
	
	
	// -------------------------------------------------------------------------
	
	
	/** '/' terminated path to the resources directory. */
	public static String PATH_RESOURCES = "resources/";
	/** '/' terminated path to the image resources directory. */
	public static String PATH_IMAGES = PATH_RESOURCES + "images/";
	/** '/' terminated path to the sound resources directory. */
	public static String PATH_SOUNDS = PATH_RESOURCES + "sounds/";
	/** '/' terminated path to the planners directory. */
	public static String PATH_PLANNING = PATH_RESOURCES + "planning/";
	/** '/' terminated path to the maps directory. */
	public static String PATH_MAPS = PATH_RESOURCES + "maps/";
	
	
	// -------------------------------------------------------------------------
	
	
	/** If set, the agents are planning with full knowledge of the world. */
	public static boolean FLAG_ALL_KNOWING_AGENTS = false;
	
	/** If set, the planning problem files are saved with a timestamp. */
	public static boolean FLAG_SAVE_PLANNING_PROBLEMS = false;
	
	/** If set, level design is done in the gameplay itself, not in different run. */
	public static boolean FLAG_IN_GAME_LEVEL_DESIGN = false;
	
	/**  */
	public static boolean FLAG_INVALIDATE_PREVIOUS_PATH = false;
	
	/** If set, the agents are replanning after gathering new knowledge. */
	public static boolean FLAG_REPLAN_ON_NEW_KNOWLEDGE = false;
	
	
	/**  */
	public static boolean FLAG_SOLID_BACKGROUND = true;
	
	
	/**  */
	public static boolean FLAG_PLAYER_CONTROL_MODE = false;
	
	
	// -------------------------------------------------------------------------
	// constructors:
	
	
	/**
	 * 
	 */
	public VisualBurglar() throws SlickException {
		// set the title:
		super(STR_TITLE);
		// set the states:
		this.addState(new MenuState(STATE_MENU));
		this.addState(new GraphicPlayState(STATE_PLAY));
		this.addState(new LevelSelectionState(STATE_LEVEL_SELECT));
		// start:
		this.enterState(STATE_MENU);
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/** 
	 * Initialize the used states.
	 * 
	 * @param container
	 */
	@Override
	public void initStatesList(GameContainer container) throws SlickException {
		this.getState(STATE_MENU).init(container, this);
		this.getState(STATE_PLAY).init(container, this);
		this.getState(STATE_LEVEL_SELECT).init(container, this);
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/** 
	 * 
	 * 
	 * arguments:
	 * "-w %d": width
	 * "-h %d": height
	 * "-r": show frame rate
	 * "-f": full screen mode
	 */
	public static void main(String[] args) {
		
		boolean showFrameRate = false;
		boolean fullScreen = false;
		boolean replanOnKnowledge = false;
		int width  = VisualBurglar.DEFAULT_WIDTH;
		int height = VisualBurglar.DEFAULT_HEIGHT;
		
		// process the arguments:
		for(int index = 0; index < args.length; index++){
			
			// frame rate:
			if(args[index].equals(STR_FRAMERATE)){
				showFrameRate = true;
				continue;
			}
			
			// full screen:
			if(args[index].equals(STR_FULLSCREEN)){
				fullScreen = true;
				continue;
			}
			
			// full screen:
			if(args[index].equals(STR_REPLAN_ON_KNOWLEDGE)){
				replanOnKnowledge = true;
				continue;
			}
			
			// width:
			if(args[index].equals(STR_WIDTH)){
				if(args.length < index + 2){
					System.out.println(STR_USAGE);
					System.exit(-1);
				}
				try{
					width = Integer.valueOf(args[++index]);
				}catch(NumberFormatException e){
					System.err.println(STR_USAGE);
					System.exit(-1);
				}
				continue;
			}
			
			// height:
			if(args[index].equals(STR_HEIGHT)){
				if(args.length < index + 2){
					System.out.println(STR_USAGE);
					System.exit(-1);
				}
				try{
					height = Integer.valueOf(args[++index]);
				}catch(NumberFormatException e){
					System.err.println(STR_USAGE);
					System.exit(-1);
				}
				continue;
			}
			
			// resources:
			if(args[index].equals(STR_RESOURCES)){
				if(index + 1 < args.length){
					VisualBurglar.changeResourcesPath(args[index + 1]);
					index++;
				}else{
					System.err.println(STR_USAGE);
					System.exit(-1);
				}
			}
		}
		
		try{
			AppGameContainer app = new AppGameContainer(new VisualBurglar());
			VisualBurglar.FLAG_REPLAN_ON_NEW_KNOWLEDGE = replanOnKnowledge;
			app.setDisplayMode(width, height, fullScreen);
			app.setShowFPS(showFrameRate);
			// render even when invisible
			app.setAlwaysRender(true);
			// synchronize the rendering cycles with the monitor's frame rate
			app.setVSync(true);
			// start the main loop:
			app.start();
		}catch(SlickException e){
			e.printStackTrace();
		}
	}
	
	
	/** Updates the resource paths. */
	public static void changeResourcesPath(String newPath) {
		PATH_RESOURCES = newPath;
		PATH_IMAGES = PATH_RESOURCES + "images/";
		PATH_SOUNDS = PATH_RESOURCES + "sounds/";
		PATH_PLANNING = PATH_RESOURCES + "planning/";
		PATH_MAPS = PATH_RESOURCES + "maps/";
	}
	
}
